package file;

import commands.BaseCmd;
import commands.CmdType;
import commands.Include;
import error.Errors;

import java.util.ArrayList;

public class Files
{
	ArrayList<File> files;
	ArrayList<File> dynamicFiles;// Для поиска анкоров в них
	ArrayList<File> includeFiles;// Для составления правильного порядка следования файлов (INCLUDE и STATIC_INCLUDE)
	BaseCmd baseCommand;

	public static Files baseFiles;

	public Files(int t)
	{
	}

	public Files(String basePath)
	{
		files = new ArrayList<File>();
		java.io.File folder = new java.io.File(basePath);

		// Формируем список файлов
		findFiles(folder);

		// Ищем совпадения алиасов
		for (int i = 0; i < files.size(); i++)
			for (int j = i + 1; j < files.size(); j++)
				if (files.get(i).fileAlias.equals(files.get(j).fileAlias))
					Errors.addError(
							files.get(j).fileName,
							files.get(j).fileAlias,
							1,
							"Алиас '" + files.get(i).fileAlias + "' продублирован в файлах '" + files
									.get(i).fileName + "' и '" + files.get(j).fileName + "'");

		// Формируем вспомогательные списки
		dynamicFiles = new ArrayList<File>();
		includeFiles = new ArrayList<File>();
		ArrayList<File> tempFile = new ArrayList<File>();
		for (File file : files)
		{
			if (file.fileType == FileType.INCLUDE || file.fileType == FileType.PARSE)
				dynamicFiles.add(file);
			if (file.fileType == FileType.INCLUDE || file.fileType == FileType.STATIC_INCLUDE)
			{
				if (file.IsAnyPlace())
					includeFiles.add(file);
				else
					tempFile.add(file);
				while (true)
					if (!(tryToAddIncludesFile(tempFile))) break;
			}
		}

		// Проверки на согласованность файлов и их заголовков
		for (File tFile : tempFile)
		{
			File temp = getFile(tFile.fileAlias);
			if (temp == null)
			{
				Errors.addError(tFile.fileName, tFile.fileAlias, 1,
						"Параметр AFTER указывает на несуществующий алиас файла: " + tFile.fileAlias);
				continue;
			}
			if (temp.fileType != FileType.INCLUDE && temp.fileType != FileType.STATIC_INCLUDE)
			{
				Errors.addError(tFile.fileName, tFile.fileAlias, 1,
						"Параметр AFTER указывает на алиас файла с типом отличным от INCLUDE и STATIC_INCLUDE: " + temp.fileType);
				continue;
			}
			Errors.addError(tFile.fileName, tFile.fileAlias, 1,
					"Параметр AFTER указывает на алиас файла ('" + tFile.fileAfter + "') не добавленного в цепочку парсинга (возможно замыкание, либо указанный файл содержал ошибку)");
		}
		tempFile.clear();
	}

	void findFiles(java.io.File folder)
	{
		for (java.io.File f : folder.listFiles())
			if (f.isFile())
			{
				if (f.getName().toLowerCase().endsWith(".mif"))
					files.add(new File(f.getAbsolutePath()));
			}
			else if (f.isDirectory())
				findFiles(f.getAbsoluteFile());
	}

	boolean tryToAddIncludesFile(ArrayList<File> tempFiles)
	{
		for (File tFile : tempFiles)
			for (File incFile : includeFiles)
				if (tFile.fileAfter.equals(incFile.fileAlias))
				{
					includeFiles.add(tFile);
					tempFiles.remove(tFile);
					return true;
				}
		return false;
	}

	public File getFile(String alias)
	{
		for (File file : files)
			if (alias.toUpperCase().equals(file.fileAlias) && file.fileType!=FileType.BAD)
				return file;
		return null;
	}

	public void generateBaseCommands()
	{
		baseCommand = new BaseCmd("AutoStyle.css", "AUTOSTYLE.CSS");
		for (File file : includeFiles)
			baseCommand.addCommandToBody(new Include(file.fileAlias,
					((file.fileType == FileType.INCLUDE) ? CmdType.INCLUDE_BEFORE : CmdType.INCLUDE_AFTER)));

		for (File file : dynamicFiles)
			file.generateCommands();
	}

	public void doIncludes()
	{
		for (File file : dynamicFiles)
			file.baseCommand.doIncludes();
		baseCommand.doIncludes();
	}

	public void print1()
	{
		System.out.println("\n");
		System.out.println("AllFiles:");
		for (File file : files)
			System.out.printf("  %s %s %s\n", file.fileAlias, file.fileType, file.fileAfter);
		System.out.println("DynamicFiles:");
		for (File file : dynamicFiles)
			System.out.printf("  %s %s %s\n", file.fileAlias, file.fileType, file.fileAfter);
		System.out.println("IncludeFiles:");
		for (File file : includeFiles)
			System.out.printf("  %s %s %s\n", file.fileAlias, file.fileType, file.fileAfter);
		System.out.println("\n");
		System.out.println("All files:");
		for (File file : files)
		{
			System.out.printf("  %s %s %s\n", file.fileAlias, file.fileType, file.fileAfter);
			if (file.fileType != FileType.BAD)
				for (FileString str : file.strings)
					System.out.printf("    %s %d %s\n", str.fileAlias, str.lineNum, str.value);
			System.out.println();
		}
	}

	public void print2()
	{
		System.out.println("Dynamic files:");
		for(File file : dynamicFiles)
		{
			System.out.printf("---=============%s===============================================---------------------------\n",file.fileAlias);
			file.baseCommand.print2();
			System.out.println();
		}

		System.out.println("<<<<<<<<<<<<<<<<Out file>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>");
		baseCommand.print2();
		System.out.println();
	}
}
